<?php
   
/**
 * Mapper for talbums
 * 
 * @author Martin Grossmann <snake.aas@gmail.com>
 * @version 1.0
 * @package Mappers
 *
 * @property-read int $idAlbum Unique identifier of the album
 * @property User $User Owner of the album
 * @property-read idUser $idUser id of owner of the album
 * @property Album $ParentAlbum Parent album. Can be null
 * @property \Doctrine\Common\Collections\ArrayCollection $ChildrenAlbums Collection of childrens. Can be empty
 * @property string $Name Name of the album. 30 chars max
 * @property string $Description Short description of the album. Can be null. 255 chars max
 * @property-read DateTime $CreationDate Date creation albums
 * @property-read DateTime $ModifyDate Last modification date for the album
 * @property Protection $Protection Access right to the album. 10 chars max
 * @property string $ProtectionName Access right to the album. 10 chars max
 * @property string $Password Password to access the album. Can be null. 40 chars max
 * @property Boolean $AllowComments If comments are allowed
 * @property int $PhotoCount Number of photos 
 * @property-read \Doctrine\Common\Collections\ArrayCollection $AllowedUsers Collection of allowed users
 * @property Photo $HeadPhoto 
 * @property-read \Doctrine\Common\Collections\ArrayCollection $FavoritesByUsers Collection of users who have this album in favorites
 * @property-read \Doctrine\Common\Collections\ArrayCollection $Photos Collection of photos inside the album
 * 
 * @entity(repositoryClass="AlbumRepository")
 * @table(name="talbums", indexes={@index(name="TAlbums_TAlbums_FK", columns="idBefore"),
 *                                 @index(name="TAlbums_TProtection_FK", columns="Protection"),
 *                                 @index(name="TAlbums_TUsers_FK", columns="idUser")},
 *                        uniqueConstraints={@UniqueConstraint(name="idBefore_idUser_name_UQ", columns={"idUser", "idBefore", "Name"})})
 * @hasLifecycleCallbacks
 */     
class Album {
  /**
   * Unique identifier of the album
   * 
   * @access private
   * @var int
   * 
   * @Id 
   * @column(name="idAlbum", type="integer")
   * @generatedValue(strategy="IDENTITY")
   */
   private $idAlbum;
     
  /**
   * Owner of the Album
   * 
   * @access private
   * @var User
   * 
   * @manyToOne(targetEntity="User", inversedBy="albums")
   * @joinColumn(name="idUser", referencedColumnName="idUser")
   */
   private $user;
   
   /**
    * @var int
    * @access private
    * 
    * @column(name="idUser", type="integer")
    */
   private $idUser;


   /**
   * Parent album. Can be null
   * 
   * @access private
   * @var Album
   * 
   * @manyToOne(targetEntity="Album", inversedBy="childrenAlbums")
   * @joinColumn(name="idBefore", referencedColumnName="idAlbum", nullable=true)
   */
   private $parentAlbum;
   
  /**
   * Children albums. Can be null
   * 
   * @access private
   * @var \Doctrine\Common\Collections\ArrayCollection
   * 
   * @oneToMany(targetEntity="Album", mappedBy="parentAlbum")
   * @OrderBy({"modifyDate" = "DESC"})
   */
   private $childrenAlbums;
     
  /**
   * Name of the album
   * 
   * @access private
   * @var string
   * 
   * @column(name="Name", type="string", length=30)
   */
   private $name;
     
  /**
   * Short description of the album. Can be null
   * 
   * @access private
   * @var string
   * 
   * @column(name="Description", type="string", length=255, nullable=true)
   */
   private $description;
     
  /**
   * Date creation albums
   * 
   * @access private
   * @var DateTime
   * 
   * @column(name="CreationDate", type="datetimetz", nullable=true)
   */
   private $creationDate;
     
  /**
   * Last modification date for the album
   * 
   * @access private
   * @var DateTime
   * 
   * @column(name="ModifyDate", type="datetimetz")
   */
   private $modifyDate;
     
  /**
   * Access right to the album.
   * 
   * @access private
   * @var Protection
   * 
   * @manyToOne(targetEntity="Protection")
   * @joinColumn(name="Protection", referencedColumnName="Protection")
   */
   private $protection;
   
   /**
    * Name of access right
    * 
    * @access private
    * @var string
    * 
    * @column(name="Protection", type="string", length=10) 
    */
   private $protectionName;
     
  /**
   * Password to access the album. Can be null
   * 
   * @access private
   * @var string
   * 
   * @column(name="Password", type="string", length=40, nullable=true)
   */
   private $password;
     
  /**
   * If comments are allowed
   * 
   * @access private
   * @var boolean
   * 
   * @column(name="AllowComments", type="boolean")
   */
   private $allowComments;
     
  /**
   * Number of photos
   * 
   * @access private
   * @var int
   * 
   * @column(name="PhotoCount", type="smallint")
   */
   private $photoCount;
   
   /**
    *
    * @access private
    * @var \Doctrine\Common\Collections\ArrayCollection
    * 
    * @manyToMany(targetEntity="User", mappedBy="accessible")
    */
   private $allowedUsers;
   
   /**
    *
    * @access private
    * @var Photo 
    * 
    * @oneToOne(targetEntity="Photo")
    * @joinColumn(name="HeadPhoto", referencedColumnName="idPhoto")
    */
   private $headPhoto;
   
   /**
    * @access private
    * @var \Doctrine\Common\Collections\ArrayCollection
    * 
    * @manyToMany(targetEntity="User", mappedBy="favoritesAlbums")    
    */
   private $favoritesByUsers;
   
   /**
    *
    * @access private
    * @var \Doctrine\Common\Collections\ArrayCollection
    * 
    * @oneToMany(targetEntity="Photo", mappedBy="album")
    * @OrderBy({"dateInserted" = "DESC"})
    */
   private $photos;

  public function __get($name) {
    
    switch($name) {
      case "idAlbum": 
        return $this->idAlbum;
        break;
    
      case "User": 
        return $this->user;
        break;
    
      case "idUser": 
        return $this->idUser;
        break;
      
      case "ParentAlbum": 
        return $this->parentAlbum; 
        break;
    
      case "ChildrenAlbums": 
        return $this->childrenAlbums; 
        break;
     
      case "Name": 
        return $this->name;
        break;
  
      case "Description": 
        return $this->description;
        break;
    
      case "CreationDate":  
        return $this->creationDate;
        break;
    
      case "ModifyDate": 
        return $this->modifyDate;
        break;
    
      case "Protection": 
        return $this->protection;
        break;
   
      case "ProtectionName": 
        return $this->protectionName;
        break;
    
      case "Password": 
        return $this->password;
        break;
   
      case "AllowComments": 
        return $this->allowComments;
        break;
    
      case "PhotoCount": 
        return $this->photoCount;
        break;
      
      case "AllowedUsers":
        return $this->allowedUsers;
        break;
      
      case "HeadPhoto":
        return $this->headPhoto;
        break;
      
      case "FavoritesByUsers":
        return $this->favoritesByUsers;
        break;
      
      case "Photos":
        return $this->photos;
        break;
        
      default: 
        throw new EntityException(sprintf(T_("Trying to get undefined property")." ", $name));
    }
  }
  
  public function __set($name, $value) {
   
    try {
    switch($name) {
      case "User":
        $this->user = Validations::ValidateObject($value, 'User');
        $this->idUser = $value->idUser;
        break;
      
      case "ParentAlbum": 
        $this->parentAlbum = Validations::ValidateObject($value, 'Album', true);
        break;
      
      case "ChildrenAlbums": 
        $this->childrenAlbums = Validations::ValidateObject($value, 'Album');
        break;

      case "Name": 
        $this->name = Validations::validateString($value, 30, Validations::regexp_albumName, false);
        break; 

      case "Description": 
        $this->description = Validations::validateString($value, 255, null, true);
        break; 

      case "Protection": 
        $this->protection = Validations::ValidateObject($value, 'Protection');
        $this->protectionName = $value->Protection;
        break; 
      
      case "ProtectionName": 
        $this->protectionName = Validations::validateString($value, 10, null, false);
        break;

      case "Password": 
        $this->password = Validations::validateString($value, 40, null, true);
        break; 

      case "AllowComments": 
        $this->allowComments = Validations::ValidateBoolean($value);
        break; 

      case "PhotoCount": 
        $this->photoCount = Validations::validateInteger($value, 0, null, false);
        break; 
      
      case "HeadPhoto": 
        $this->headPhoto = Validations::ValidateObject($value, 'Photo');

      default: 
        throw new EntityException(sprintf(T_("Trying to set undefined property")." ", $name));
      
    }
    } catch (DomainException $ex) {
      throw new EntityException($name.$ex->getMessage());
    } catch (LengthException $ex) {
      throw new EntityException($name.$ex->getMessage());
    } catch (UnexpectedValueException $ex) {
      throw new EntityException(T_($name).$ex->getMessage());
    }
  }  
  
  public function addChildren(Album $album) {
    $this->childrenAlbums->add($album);
    $album->parentAlbum = $this;
  }
  
  public function addPhoto(Photo $photo) {
    $this->photos->add($photo);
    $photo->Album = $this;
  }
    
  public function addAllowedUser(User $user) {
    $this->allowedUsers->add($user);
    $user->addAccessible($this);
  }
  
  public function removeAllowedUser(User $user) {
    $this->allowedUsers->removeElement($user);
    $user->removeAccessible($this);
  }
  
  public function addFollower(User $user) {
    $this->favoritesByUsers->add($user);
  }
  
  public function __construct() {
    $this->childrenAlbums = new \Doctrine\Common\Collections\ArrayCollection();
    $this->parentAlbum = null;
    $this->allowedUsers = new \Doctrine\Common\Collections\ArrayCollection();
    $this->favoritesByUsers = new \Doctrine\Common\Collections\ArrayCollection();
    $this->photoCount = 0;
  }
  
  /**
   * @preUpdate
   */
  public function preUpdate() {
    $this->modifyDate = new DateTime('now');
  }
  
  /**
   * @prePersist
   */
  public function preInsert() {
    $this->modifyDate   = new DateTime('now');
    $this->creationDate = new DateTime('now');
  }
  
}